package com.admin.util;

import com.jcraft.jsch.*;
import org.slf4j.Logger;

import java.io.InputStream;
import java.util.Properties;
import java.util.Vector;

public class SFTPUtil {
    private static Logger log = LogUtil.getBussinessLogger();

    private static ChannelSftp sftp;

    private Session session;
    /**
     * FTP 登录用户名
     */
    private String username;
    /**
     * FTP 登录密码
     */
    private String password;
    /**
     * 私钥
     */
    private String privateKey;
    /**
     * FTP 服务器地址IP地址
     */
    private String host;
    /**
     * FTP 端口
     */
    private int port;


    /**
     * 构造基于密码认证的sftp对象
     *
     * @param username
     * @param password
     * @param host
     * @param port
     */
    public SFTPUtil(String username, String password, String host, int port) {
        this.username = username;
        this.password = password;
        this.host = host;
        this.port = port;
    }

    /**
     * 构造基于秘钥认证的sftp对象
     *
     * @param username
     * @param host
     * @param port
     * @param privateKey
     */
    public SFTPUtil(String username, String host, int port, String privateKey) {
        this.username = username;
        this.host = host;
        this.port = port;
        this.privateKey = privateKey;
    }

    public SFTPUtil() {
        this.username = "root";
        this.password = "QZY930723qzy";
        this.host = "132.232.242.236";
        this.port = 22;
    }

    /**
     * 连接sftp服务器
     *
     * @throws Exception
     */
    public void login() {
        try {
            JSch jsch = new JSch();
            if (privateKey != null) {
                jsch.addIdentity(privateKey);// 设置私钥
                log.info("sftp connect,path of private key file：{}", privateKey);
            }
            log.info("sftp connect by host:{} username:{}", host, username);

            session = jsch.getSession(username, host, port);
            log.info("Session is build");
            if (password != null) {
                session.setPassword(password);
            }
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");

            session.setConfig(config);
            session.connect();
            log.info("Session is connected");

            Channel channel = session.openChannel("sftp");
            channel.connect();
            log.info("channel is connected");

            sftp = (ChannelSftp) channel;
            log.info(String.format("sftp server host:[%s] port:[%s] is connect successfull", host, port));
        } catch (JSchException e) {
            log.error("Cannot connect to specified sftp server : {}:{} \n Exception message is: {}", new Object[]{host, port, e.getMessage()});
        }
    }

    /**
     * 关闭连接 server
     */
    public void logout() {
        if (sftp != null) {
            if (sftp.isConnected()) {
                sftp.disconnect();
                log.info("sftp is closed already");
            }
        }
        if (session != null) {
            if (session.isConnected()) {
                session.disconnect();
                log.info("sshSession is closed already");
            }
        }
    }

    /**
     * 将输入流的数据上传到sftp作为文件
     *
     * @param directory    上传到该目录
     * @param sftpFileName sftp端文件名
     * @param input        输入流
     * @throws SftpException
     * @throws Exception
     */
    public boolean upload(String directory, String sftpFileName, InputStream input) throws SftpException {
        String parentDirectory=directory.substring(0,directory.lastIndexOf("/"));//先打開父级文件
        try {
            sftp.cd(parentDirectory);
            try {
                sftp.cd(directory);
            }catch (SftpException a){
                sftp.mkdir(directory);
                sftp.cd(directory);
            }
        } catch (SftpException e) {
            log.warn("directory is not exist");
            sftp.mkdir(parentDirectory);
            try {
                sftp.cd(directory);
            }catch (SftpException a){
                sftp.mkdir(directory);
                sftp.cd(directory);
            }
        }
        sftp.put(input, sftpFileName);
        log.info("file:{} is upload successful", sftpFileName);
        return true;
    }

    /**
     * 删除文件
     *
     * @param directory  要删除的文件
     * @param isFile  是否是文件夹
     * @throws Exception
     */
    public  void delete(String directory,boolean isFile)throws Exception {
        if(isFile){
            try {
                sftp.cd(directory);
            } catch (SftpException e) {
                return;
            }
        }
        if (!CommonUtil.isEmpty(directory)) {
            Vector<ChannelSftp.LsEntry> vector = sftp.ls(directory);
            if (vector.size() == 1) { // 文件，直接删除
                sftp.rm(directory);
            } else if (vector.size() == 2) { // 空文件夹，直接删除
                sftp.rmdir(directory);
            } else {
                String fileName = "";
                // 删除文件夹下所有文件
                for (ChannelSftp.LsEntry en : vector) {
                    fileName = en.getFilename();
                    if (".".equals(fileName) || "..".equals(fileName)) {
                        continue;
                    } else {
                        delete(directory + "/" + fileName,false);
                    }
                }
                // 删除文件夹
                sftp.rmdir(directory);
            }
        }

    }

    /**
     * 移动文件
     *
     * @param oldPath
     * @param newPath
     */
    public boolean rename(String directory, String oldPath, String newPath) throws Exception {
        if (CommonUtil.isEmpty(oldPath) || CommonUtil.isEmpty(newPath)) {
            return false;
        }
        try {
            sftp.cd(directory);
            sftp.rename(oldPath, newPath);
            return true;
        } catch (SftpException e) {
            sftp.mkdir(directory);
            sftp.cd(directory);
            try {
                sftp.rename(oldPath, newPath);
                return true;
            } catch (SftpException a) {
                return false;
            }
        }
    }
}
